
#include "stdafx.h"

#include "game\game_main.h"
#include "render.h"

#include <windows.h>
#include <commctrl.h>
#include <d3d9.h>

extern HINSTANCE g_hInstance;

REND_SYSTEM * rendSys = NULL;

LPDIRECT3DDEVICE9 g_pDevice = NULL;
LPDIRECT3D9 g_pD3D = NULL;
HWND g_mainWnd;

const char * GAME_CLASS_NAME = "QubeWorldClass";
const char * GAME_WINDOW_NAME = "QubeWorld";

static bool create_window(int width, int height);

/******************************************************************************/
/* render_initialize
/*
/******************************************************************************/
bool render_initialize(void)
{
   int width   = gameConfig->GetInt("render", "width",  640);
   int height  = gameConfig->GetInt("render", "height", 480);

   if (!create_window(width, height)) {
      return false;
   }

   rendSys = NewObj(REND_SYSTEM);
   if (!rendSys->Init()) {
      return false;
   }

   return true;
}

/******************************************************************************/
/* render_term
/*
/******************************************************************************/
void render_term(void)
{
   rendSys->Term();
   Delete(rendSys);
}

/******************************************************************************/
/* render_frame
/*
/******************************************************************************/
void render_frame(void)
{
   rendSys->Update();

   MSG   msg;
   while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
   }
}

/******************************************************************************/
/* _gsWndProc
/*
/******************************************************************************/
LRESULT WINAPI _WndProc(HWND wndHandle, UINT msg, WPARAM wParam, LPARAM lParam)
{
   switch (msg) {
      case WM_CLOSE:
         gameState.stopping = true;
         //gsMsgStopLoop();
         return 0L;
      case WM_SETFOCUS:
         //_SetStateYes(gsAppState2, GS_STA2_INP_FOCUS);
         return 0;
      case WM_KILLFOCUS:
         //_SetStateNo(gsAppState2, GS_STA2_INP_FOCUS);
         return 0;
      case WM_ACTIVATE:
         //if (gsSysInput && gsSysInput->GetInput()) {
         //   gsSysInput->GetInput()->Acquire(true);
         //}
         if (!LOWORD(wParam)) {
            // Don't process 'Deactivate app'
            break;
         }
         break;
      case WM_ACTIVATEAPP:
         //// ASSERT(_IsState(gsAppState, GS_STA_SAFEENTRY));

         //if (wParam) {
         //   _SetStateYes(gsAppState, GS_STA_ACTIVATED);
         //   if (gsSysInput && gsSysInput->GetInput()) {
         //      gsSysInput->GetInput()->Acquire(true);
         //   }
         //   apDumpLog("TimeShift_ALT_TAB.log", "WM_ACTIVATEAPP: Yes     gsAppState = 0x%08X\n", gsAppState);
         //} else {
         //   if (!isWorkInactiveDBG) {
         //      BOOL ret = FALSE;
         //      EnumThreadWindows(lParam, _gswEnumWndIsConsole, (LPARAM)&ret);
         //      /*
         //      HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, lParam);
         //      DWORD procId = GetProcessIdOfThread(hThread);
         //      CloseHandle(hThread);

         //      HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, procId);

         //      CloseHandle(hProc);
         //      */

         //      if (!keepGameWorkingOnDeactive && !ret) {
         //         _SetStateNo(gsAppState, GS_STA_ACTIVATED);
         //         _SetStateYes(gsAppState, GS_STA_HW_REINIT_REQ);
         //      }
         //      apDumpLog("TimeShift_ALT_TAB.log", "WM_ACTIVATEAPP: No   gsAppState = 0x%08X\n", gsAppState);
         //   }
         //}
         return 0;
      case WM_KEYDOWN:
         // clear this flag once a key is pressed
         //if (_IsState(gsAppState, GS_STA_WAIT_FOR_ANY_KEY)) {
         //   _SetStateNo(gsAppState, GS_STA_WAIT_FOR_ANY_KEY);
         //   gsSysInput->GetInput()->FlushBuffers();
         //   return 0L;
         //}
         //if (!_IsState(gsAppState, GS_STA_RETAIL_VER)) { //for show debug window only
         //   // check for showing options dialog                  
         //   if (wParam == VK_ESCAPE && !gsMsgIsMode(GS_MODE_FREEZE))   {
         //      // gotta check most significant bit of VK_SHIFT - MSDN (yeah all those bugs with windows showing when you just hit esc)
         //      if (GetAsyncKeyState(VK_SHIFT) < 0 /*&& !gsMsgIsMode(GS_MODE_CINEMATIC) && !gsMsgIsMode(GS_MODE_FMV)*/)  {
         //         FIRE_EVENT0(sysUIShowed);
         //         if (!gsVideoShowOptions()) {
         //            gsMsgStopLoop();
         //         }
         //         FIRE_EVENT0(sysUIHidden);
         //      }
         //      gsSysInput->GetInput()->FlushBuffers();
         //   }
         //}
         return 0L;
      case WM_SYSKEYDOWN:
         if (wParam == VK_F4 && GetAsyncKeyState(VK_MENU) < 0) {
            //TerminateProcess(GetCurrentProcess(), 0);
            // ALT+F4
            //gsSysAnitec->OnEscape();
            //gsMsgStopLoop();

            gameState.stopping = true;
         }
         // Check fullscreen / window modes
         //if (!_IsState(gsAppState, GS_STA_RETAIL_VER)) {
         //   if (wParam == VK_RETURN && GetAsyncKeyState(VK_MENU) < 0) {
         //      // Switch fullscreen / window mode (if available)
         //      gsVideoSetHWMode(GS_VIDEO_HW_TOGGLE);
         //   }
         //   if (wParam == VK_F1 && GetAsyncKeyState(VK_MENU) < 0) {
         //      // ALT+F1
         //      HWND w = FindWindow(NULL, "Saber3d Console Duo");
         //      if (w != NULL) {
         //         SwitchToThisWindow(w, TRUE);
         //      }
         //   }
         //}
         return 0L;
      case WM_KEYUP:
      case WM_SYSKEYUP:
         return 0L;
      case WM_INITMENU:
         return 0L;
      case WM_SYSCOMMAND:
         switch (wParam & 0xFFF0) {
            case  SC_SCREENSAVE:       // disable screensaver
               return 0;
            case SC_CONTEXTHELP:
            case SC_KEYMENU:           // Disable Alt+Space command
            case SC_DEFAULT:
            case SC_HOTKEY:
            case SC_MONITORPOWER:
            case SC_MOUSEMENU:
            case SC_TASKLIST:
            case SC_CLOSE:
            case SC_MOVE:
            case SC_SIZE:
               return 0;
//            case SC_MAXIMIZE:
//               gsVideoSetHWMode(GS_VIDEO_HW_FULLSCR);
         };
         break;
      case WM_ERASEBKGND:
         // else
         return TRUE;
   }

   return DefWindowProc(wndHandle, msg, wParam, lParam);
}

/******************************************************************************/
/* create_window
/*
/******************************************************************************/
static bool create_window(int width, int height)
{
   WNDCLASSEX              wclass;
   INITCOMMONCONTROLSEX    icc;

   InitCommonControls();

   //// Save the current sticky/toggle/filter key settings so they can be restored them later
   //SystemParametersInfo(SPI_GETSTICKYKEYS, sizeof(STICKYKEYS), &g_StartupStickyKeys, 0);
   //SystemParametersInfo(SPI_GETTOGGLEKEYS, sizeof(TOGGLEKEYS), &g_StartupToggleKeys, 0);
   //SystemParametersInfo(SPI_GETFILTERKEYS, sizeof(FILTERKEYS), &g_StartupFilterKeys, 0);

   //// Disable when full screen
   //AllowAccessibilityShortcutKeys(TRUE);

   icc.dwSize = sizeof(icc);
   icc.dwICC  = ICC_INTERNET_CLASSES;
   InitCommonControlsEx(&icc);

   // Registry main window class
   memset(&wclass, 0, sizeof(wclass));
   wclass.cbSize = sizeof(WNDCLASSEX);
   wclass.hIconSm = NULL; // Icon
   wclass.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE;
   wclass.lpfnWndProc = _WndProc;
   wclass.cbClsExtra = 0;
   wclass.cbWndExtra = 0;
   wclass.hInstance = (HINSTANCE)g_hInstance;
   //if (creatData.iconID >= 0) {
   //   wclass.hIcon = (HICON)LoadImage((HINSTANCE)apHInstance, MAKEINTRESOURCE(creatData.iconID), IMAGE_ICON, 32, 32, 0);
   //   wclass.hIconSm = (HICON)LoadImage((HINSTANCE)apHInstance, MAKEINTRESOURCE(creatData.iconID), IMAGE_ICON, 16, 16, 0);
   //} else {
      wclass.hIcon = (HICON)NULL;
      wclass.hIconSm = (HICON)NULL;
   //}
   wclass.hCursor = LoadCursor(NULL, IDC_ARROW);
   wclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
   wclass.lpszMenuName = NULL;
   //wclass.lpszClassName = creatData.winClassName;
   wclass.lpszClassName = GAME_CLASS_NAME;
   if (!RegisterClassEx(&wclass)) {
      if (!RegisterClass((LPWNDCLASS)&wclass.style)) {
         return false;
      }
   }

   //    int xPos = 0, yPos = 0;
   //    apCfgRead("VIDEO", "xWinPos", xPos);
   //    apCfgRead("VIDEO", "yWinPos", yPos);

   // Create main window
   g_mainWnd = CreateWindowEx(0L, GAME_CLASS_NAME, GAME_WINDOW_NAME, WS_BORDER | WS_SYSMENU | WS_VISIBLE/*WS_OVERLAPPED | WS_CAPTION*/, 0, 0, width, height, NULL, NULL, (HINSTANCE)g_hInstance, NULL);
   if (!g_mainWnd) {
      return false;
   }

   //_gsMainWndStyle = GetWindowLong((HWND)apHMainWindow, GWL_STYLE);
   ShowWindow(g_mainWnd, SW_SHOW);
   UpdateWindow(g_mainWnd);

   // clear system menu !!!!!
   HMENU menu = GetSystemMenu((HWND)g_mainWnd, FALSE);
   for (int i = 0; i < 10; i ++) {
      DeleteMenu(menu, 0, MF_BYPOSITION);
   }

   return true;
}

/******************************************************************************/
/* REND_SYSTEM::Init
/*
/******************************************************************************/
bool REND_SYSTEM::Init(void)
{
   g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
   if (g_pD3D == NULL) {
      ShowErrorMsg("Failed to initialize Direct 3D");
      return false;
   }

   int adapter = 0;

   D3DPRESENT_PARAMETERS pparams;
   ZeroStruct(&pparams);

   RECT rc;
   GetClientRect((HWND)g_mainWnd, &rc);
   pparams.BackBufferHeight = rc.bottom - rc.top;
   pparams.BackBufferWidth = rc.right - rc.left;
   pparams.BackBufferFormat = D3DFMT_A8R8G8B8;
   pparams.BackBufferCount = 1; 
   pparams.MultiSampleType = D3DMULTISAMPLE_NONE;
   pparams.MultiSampleQuality = 0;
   pparams.SwapEffect = D3DSWAPEFFECT_DISCARD;
   pparams.hDeviceWindow = (HWND)g_mainWnd;
   pparams.Windowed = TRUE;
   pparams.EnableAutoDepthStencil = FALSE;
   pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

   HRESULT res = g_pD3D->CreateDevice(adapter, D3DDEVTYPE_HAL, g_mainWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &pparams, &g_pDevice);
   if (FAILED(res)) {
      ShowErrorMsg("Failed to create D3D device");
      return false;
   }

   return true;
}

/******************************************************************************/
/* REND_SYSTEM::Term
/*
/******************************************************************************/
void REND_SYSTEM::Term(void)
{
   SAFE_RELEASE(g_pDevice);
   SAFE_RELEASE(g_pD3D);
}

/******************************************************************************/
/* REND_SYSTEM::Update
/*
/******************************************************************************/
void REND_SYSTEM::Update(void)
{
   g_pDevice->BeginScene();
   g_pDevice->Clear(0, NULL, D3DCLEAR_TARGET /*| D3DCLEAR_ZBUFFER*/, 0, 1.f, 0);
   g_pDevice->EndScene();

   g_pDevice->Present(NULL, NULL, NULL, NULL);
}